package com.eobard.config.security;

import com.eobard.filter.CheckTokenFilter;
import com.eobard.handler.AnonymousAuthenticationHandler;
import com.eobard.handler.AuthAccessDeniedHandler;
import com.eobard.handler.LoginFailureHandler;
import com.eobard.handler.LoginSuccessHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * @author Eobard_Thawne
 * @version 1.0
 * @date 2022/8/6 -18:21
 */
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {


    @Resource
    private LoginSuccessHandler loginSuccessHandler;

    @Resource
    private LoginFailureHandler failureHandler;

    @Resource
    private AuthAccessDeniedHandler authAccessDeniedHandler;

    @Resource
    private AnonymousAuthenticationHandler anonymousAuthenticationHandler;

    @Resource
    private CustomUserDetailsService userDetailsService;

    @Resource
    private CheckTokenFilter checkTokenFilter;

    /**
     *  处理登录认证(前后端分离):
     *      不需要session、不需要具体的登录成功、登陆失败、匿名访问、无权限访问路径,只需要让对应的处理器去完成逻辑即可
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //登录前过滤添加过滤器过滤
        http.addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class);

        http.formLogin()
                .usernameParameter("username")                              //设置前端页面登录用户名的name属性值
                .passwordParameter("password")                              //设置前端页面登录密码的name属性值
//                .loginProcessingUrl("/api/user/login")                      //登录请求url地址
                .loginProcessingUrl(loginUrl)
                .successHandler(loginSuccessHandler)                        //认证成功处理器
                .failureHandler(failureHandler)                             //认证失败处理器
                .and()
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)     //不创建session
                .and()
                .authorizeRequests()                                        //设置需要拦截的请求路径
                .antMatchers("api/user/login/").permitAll()      //过滤登录路径
                .anyRequest().authenticated()                               //其它路径必须要认证才能访问
                .and()
                .exceptionHandling()
                .accessDeniedHandler(authAccessDeniedHandler)               //认证用户无权限处理器
                .authenticationEntryPoint(anonymousAuthenticationHandler)   //匿名用户无权限处理器
                .and()
                .cors()                                                     //开启跨域请求
                ;
    }



    /**
     * 配置认证处理器
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }


    //注入加密类
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }


    @Value("${request.login.url}")
    private String loginUrl;

    public String getLoginUrl() {
        return loginUrl;
    }

    public void setLoginUrl(String loginUrl) {
        this.loginUrl = loginUrl;
    }
}
